package org.jeecg.modules.iot.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.iot.cache.EBikeCache;
import org.jeecg.modules.iot.model.FieldStatus;
import org.jeecg.modules.iot.model.Location;
import org.jeecg.modules.iot.model.Track.Tracking;
import org.jeecg.modules.iot.model.power.TaiPower;
import org.jeecg.modules.iot.mqtt.server.service.processor.carOperate.CarService;
import org.jeecg.modules.iot.mqtt.server.service.processor.control.ControlService;
import org.jeecg.modules.iot.service.ILocationService;
import org.jeecg.modules.iot.service.IPowerService;
import org.jeecg.modules.iot.utils.JsonUtil;
import org.jeecg.modules.rental.api.IRentalEBikeAPI;
import org.jeecg.modules.rental.entity.RentalEBike;
import org.jeecg.modules.websocket.constant.WsMessageConstant;
import org.jeecg.modules.websocket.enums.WsBussinesType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

@Slf4j
@RestController
@RequestMapping("/iot/car") // Added mapping for consistency
@Api(tags = "电池控制层")
public class CarController {

    @Autowired
    private EBikeCache eBikeCache;
    @Autowired
    private CarService carService;
    @Autowired
    private IPowerService powerService;

    @Autowired
    private ControlService controlService;
    @Autowired
    private ILocationService locationService;
    @Autowired
    private JeecgRedisClient jeecgRedisClient;



    @Autowired
    private RedisUtil redisUtil;

    private static final String NATIONAL_STANDARD_SPEED_LIMIT_KEY = "vehicle:%s:nationalStandardSpeedLimit"; //  Redis key 格式


    @PostMapping("/pushInfo/{imei}")
    public Boolean pushInfo(@PathVariable String imei){
        // 从 locationService 查询位置信息
        Location location = locationService.queryByDeviceId(imei);
        if (location != null) {
            // 创建 Tracking 对象，并设置里程信息
            Tracking tracking = new Tracking();
            tracking.setRMileage(roundToTwoDecimalPlaces((float) Math.abs(location.getRMileage() / 1000.0)));
            String onlineStatus = eBikeCache.getVehicleOnlineStatus(imei);
            // 创建并发送跟踪信息
            sendMessageToQueue(imei, WsBussinesType.TRACKING.getCode(), tracking);
            location.setOnlineStatus(onlineStatus);
            // 创建并发送位置信息
            sendMessageToQueue(imei, WsBussinesType.LOCATION.getCode(), location);
        }

        // 从 powerService 查询电池信息
        TaiPower power = powerService.queryLastByDeviceId(imei);
        if (power != null) {
            // 创建并发送电池信息
            sendMessageToQueue(imei, WsBussinesType.POWER.getCode(), power);
        }
        FieldStatus fieldStatus = eBikeCache.getFieldStatus(imei);
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode objectNode = objectMapper.createObjectNode();
        String sportModeRedisKey = String.format(NATIONAL_STANDARD_SPEED_LIMIT_KEY, imei);
        Boolean sportModeEnabled = (Boolean) redisUtil.get(sportModeRedisKey); // 从 Redis 获取运动模式状态
        boolean sportMode = sportModeEnabled != null && sportModeEnabled; // 简化逻辑
        if (fieldStatus != null) {
            fieldStatus.setSportMode(sportMode);
            objectNode.put("acc", fieldStatus.isAcc());
            objectNode.put("doorLocked", fieldStatus.isDoorLocked());
            objectNode.put("sportMode", sportMode);
            String satusJson= JsonUtil.createPubJson(WsBussinesType.OTHER.getCode(),true,fieldStatus);
            BaseMap satusParams = new BaseMap();
            satusParams.add("terminalCode", imei);
            satusParams.add("message", satusJson);
            jeecgRedisClient.sendMessage(WsMessageConstant.EBIKE_REALTIME_MESSAGE, satusParams);
        }
        return true;
    }


    @PostMapping("/openCar/{imei}/{sn}")
    public Boolean openCar(@PathVariable String imei, @PathVariable String sn) throws ExecutionException, InterruptedException, TimeoutException {
        // 根据 imei 和 sn 获取 RentalEBike 对象，这部分需要根据你的实际情况实现
        RentalEBike car = getRentalEBike(imei, sn);

        return  carService.openCar(car);
    }


    @PostMapping("/enableSportMode/{imei}/{sn}")
    public Boolean enableSportMode(@PathVariable String imei, @PathVariable String sn, @RequestParam Boolean enable) throws ExecutionException, InterruptedException, TimeoutException {
        // 根据 imei 和 sn 获取 RentalEBike 对象，这部分需要根据你的实际情况实现
        RentalEBike car = getRentalEBike(imei, sn);
        Boolean isSend =controlService.enableSportMode(car,enable);
        String redisKey = String.format(NATIONAL_STANDARD_SPEED_LIMIT_KEY, imei);
        redisUtil.set(redisKey, enable);
        return  isSend;
    }


    @PostMapping("/closeCar/{imei}/{sn}")
    public Boolean closeCar(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return  carService.closeCar(car);
    }

    @PostMapping("/defenseCar/{imei}/{sn}")
    public Boolean defenseCar(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return  carService.defenseCar(car) ;
    }


    @PostMapping("/disarmingCar/{imei}/{sn}")
    public Boolean disarmingCar(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
         return  carService.disarmingCar(car);
    }


    @PostMapping("/handleLockOpen/{imei}/{sn}")
    public Boolean handleLockOpen(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.handleLockOpen(car);
    }

    @PostMapping("/handleLockClose/{imei}/{sn}")
    public Boolean handleLockClose(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.handleLockClose(car);
    }

    @PostMapping("/searchCar/{imei}/{sn}")
    public Boolean searchCar(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.searchCar(car);
    }

    @PostMapping("/seatLock/{imei}/{sn}")
    public Boolean seatLock(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.seatLock(car);
    }

    @PostMapping("/pairRemoteControl/{imei}/{sn}")
    public Boolean pairRemoteControl(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.pairRemoteControl(car);
    }

    @PostMapping("/clearRemoteControl/{imei}/{sn}")
    public Boolean clearRemoteControl(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.clearRemoteControl(car);
    }

    @PostMapping("/setPlayAudio/{imei}/{sn}")
    public Boolean setPlayAudio(@PathVariable String imei, @PathVariable String sn, @RequestParam Byte audioIndex) {
        RentalEBike car = getRentalEBike(imei, sn);
        return carService.setPlayAudio(car, audioIndex);
    }

    // ... 其他控制接口，例如 closeCar, defenseCar 等，类似于 openCar 的实现

    @PostMapping("/startLocationTrack/{imei}/{sn}")
    public Result<?> startLocationTrack(@PathVariable String imei, @PathVariable String sn, @RequestParam Short timeInterval, @RequestParam int validityPeriod) {
        RentalEBike car = getRentalEBike(imei, sn);
        if (carService.startLocationTrack(car, timeInterval, validityPeriod)) {
            return Result.OK("启动位置追踪成功");
        } else {
            return Result.error("启动位置追踪失败");
        }
    }


    @GetMapping("/getSportModeStatus/{imei}/{sn}") //  使用 GetMapping
    public Result<Boolean> getSportModeStatus(@PathVariable String imei, @PathVariable String sn) {
        try {
            RentalEBike car = getRentalEBike(imei, sn);
            Boolean isSportModeEnabled = controlService.getSportModeStatus
                    (car); // 调用 ControlService 的方法
            return Result.OK(isSportModeEnabled);
        } catch (Exception e) {
            return Result.error("获取运动模式状态失败：" + e.getMessage());
        }
    }




    @ApiOperation("根据序列号查询位置")
    @PostMapping("/returnCar/{imei}/{sn}")
    public Result<?> returnCar(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        if (carService.returnCar(car)) {
            return Result.OK("还车成功"); // 注意：还车操作是异步的，这里返回成功只表示请求已提交
        } else {
            return Result.error("还车失败"); //  这部分逻辑可能需要根据实际情况调整
        }
    }

    @PostMapping("/setVolume/{imei}/{sn}")
    public Boolean setVolume(@PathVariable String imei, @PathVariable String sn, @RequestParam Integer volume) {
        RentalEBike car = getRentalEBike(imei, sn);
        return  carService.setVolume(car, volume);
    }

    // ... 其他控制接口，例如 pairRemoteControl, clearRemoteControl 等

    // ---------- 车辆查询 ----------

    @PostMapping("/queryLocation/{imei}/{sn}")
    public Result<?> queryLocation(@PathVariable String imei, @PathVariable String sn) {
        RentalEBike car = getRentalEBike(imei, sn);
        if (car == null) {
            return Result.error("车辆不存在");
        }
        return carService.queryLocation(car);
    }


    // ... 其他查询接口


    private RentalEBike getRentalEBike(String imei, String sn) {
        RentalEBike car= new RentalEBike();
        car.setCarCode(imei);
        car.setPhone(sn);
        return car;
    }

    private void sendMessageToQueue(String carCode, Integer businessType, Object messageObject) {
        // 将业务对象转换为 JSON 格式
        String messageJson = JsonUtil.createPubJson(businessType, true, messageObject);

        BaseMap messageParams = new BaseMap();
        messageParams.add("terminalCode", carCode);
        messageParams.add("message", messageJson);
        jeecgRedisClient.sendMessage(WsMessageConstant.EBIKE_REALTIME_MESSAGE, messageParams);
    }

    public static float roundToTwoDecimalPlaces(Float value) {
        // 检查是否为空或无效值
        if (value == null || Float.isNaN(value) || Float.isInfinite(value)) {
            return 0f;
        }
        BigDecimal bd = new BigDecimal(Float.toString(value));
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        return bd.floatValue();
    }



}